package com.tuesda.walker.circlerefresh;


import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DependentLayout;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.multimodalinput.event.TouchEvent;


public class CircleRefreshLayout extends DependentLayout implements Component.TouchEventListener {


    private static final long BACK_TOP_DUR = 600;
    private static final long REL_DRAG_DUR = 200;

    private int mHeaderBackColor = 0xff8b90af;
    private int mHeaderForeColor = 0xffffffff;
    private int mHeaderCircleSmaller = 6;


    private float mPullHeight;
    private float mHeaderHeight;
    private Component mChildView;
    private AnimationView mHeader;
    private float mTouchStartY;

    private float mTouchCurY;

    private AnimatorValue mUpBackAnimator;


    private static final String AniBackColor = "AniBackColor";
    private static final String AniForeColor = "AniForeColor";
    private static final String CircleSmaller = "CircleSmaller";
    private float lastX = 0;
    private float lastY = 0;
    private float downTY = 0;
    private EventHandler eventHandler = new EventHandler(EventRunner.create());


    public CircleRefreshLayout(Context context) {
        this(context, null, null);
    }

    public CircleRefreshLayout(Context context, AttrSet attrs) {
        this(context, attrs, null);
    }

    public CircleRefreshLayout(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
        setTouchEventListener(this);
    }


    private void init(Context context, AttrSet attrs) {

        if (getChildCount() > 1) {
            throw new RuntimeException("you can only attach one child");
        }
        setAttrs(attrs);
        mPullHeight = 300;
        mHeaderHeight = 200;
        mChildView = getComponentAt(0);
        addHeaderView();
    }

    private void setAttrs(AttrSet attrs) {

        boolean isPresentAniBackColor = attrs.getAttr(AniBackColor).isPresent();
        if (isPresentAniBackColor) {
            mHeaderBackColor = attrs.getAttr(AniBackColor).get().getColorValue().getValue();
        }

        boolean isPresentAniForeColor = attrs.getAttr(AniForeColor).isPresent();
        if (isPresentAniForeColor) {
            mHeaderForeColor = attrs.getAttr(AniForeColor).get().getColorValue().getValue();
        }
        boolean isPresentCircleSmaller = attrs.getAttr(CircleSmaller).isPresent();
        if (isPresentCircleSmaller) {
            mHeaderCircleSmaller = attrs.getAttr(CircleSmaller).get().getIntegerValue();
        }
    }

    private void addHeaderView() {
        mHeader = new AnimationView(getContext());
        LayoutConfig paramsL = new LayoutConfig(ComponentContainer.LayoutConfig.MATCH_CONTENT, (int) mPullHeight);
        mHeader.setLayoutConfig(paramsL);
        addComponent(mHeader);
        mHeader.setAniBackColor(mHeaderBackColor);
        mHeader.setAniForeColor(mHeaderForeColor);
        mHeader.setRadius(mHeaderCircleSmaller);

        setUpChildAnimation();
    }

    private void setUpChildAnimation() {
        mUpBackAnimator = new AnimatorValue();
        mUpBackAnimator.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                float val = v;
                if (mChildView != null) {
                    mChildView.setTranslationY(val * mPullHeight);
                }
            }
        });
        mUpBackAnimator.setDuration(REL_DRAG_DUR);
    }

    @Override
    public void addComponent(Component child) {
        mChildView = child;
        super.addComponent(child);
        setUpChildAnimation();
    }

    private boolean canChildScrollUp() {
        if (mChildView == null) {
            return false;
        }
        return false;
    }

    public void finishRefreshing() {
        if (onCircleRefreshListener != null) {
            onCircleRefreshListener.completeRefresh();
        }
        CircleConstant.setIsRefreshIng(false);
        CircleConstant.setIsFinishRefresh(true);
        mHeader.setRefreshing(false);
        finishRefresh();
    }

    private OnCircleRefreshListener onCircleRefreshListener;

    public void setOnRefreshListener(OnCircleRefreshListener onCircleRefreshListener) {
        this.onCircleRefreshListener = onCircleRefreshListener;
    }


    @Override
    public boolean onTouchEvent(Component component, TouchEvent event) {
        if (CircleConstant.IS_REFRESH_ING && mHeader.getVisibility() == VISIBLE) {
            return true;
        }
        float x = event.getPointerPosition(0).getX();
        float y = event.getPointerPosition(0).getY();
        switch (event.getAction()) {

            case TouchEvent.PRIMARY_POINT_DOWN:
                downTY = y;
                lastY = y;
                lastX = x;
                return true;
            case TouchEvent.POINT_MOVE:
                mTouchCurY = event.getPointerPosition(0).getY();
                float ddY = Math.abs(y - lastY);
                float ddX = Math.abs(x - lastX);
                boolean ddown = y > lastY ? true : false;
                lastY = y;
                lastX = x;
                if (ddX < 8 && ddY > 8 && !ddown) {
                    return true;
                }
                if (ddX < 8 && ddY > 8 && ddown && ((downTY - getTop()) < 100)) {
                    float dy = mTouchCurY - mTouchStartY;
                    dy = Math.min(mPullHeight * 2, dy);
                    dy = Math.max(0, dy);

                    if (mChildView != null) {
                        mChildView.setTranslationY((dy / 2 / mPullHeight) * dy / 2);
                        float offsetY = (dy / 2 / mPullHeight) * dy / 2;
                        mHeader.getLayoutConfig().height = (int) offsetY;
                        mHeader.invalidate();
                    }
                    if (dy > 20) {
                        mHeader.setVisibility(VISIBLE);
                        CircleConstant.IS_FINISH_REFRESH = false;
                    }
                }
                return true;
            case TouchEvent.PRIMARY_POINT_UP:
            case TouchEvent.CANCEL:
                if (mChildView != null) {
                    if (mChildView.getTranslationY() >= mHeaderHeight && !CircleConstant.IS_FINISH_REFRESH) {
                        mUpBackAnimator.start();
                        mHeader.releaseDrag();
                        CircleConstant.IS_REFRESH_ING = true;
                        if (onCircleRefreshListener != null) {
                            onCircleRefreshListener.refreshing();
                        }
                        eventHandler.postTask(new Runnable() {
                            @Override
                            public void run() {
                                while (mChildView.getTranslationY() >= mHeaderHeight) {
                                    getContext().getUITaskDispatcher().asyncDispatch(new Runnable() {
                                        @Override
                                        public void run() {
                                            if (CircleConstant.IS_FINISH_REFRESH) {
                                                mHeader.invalidate();
                                            } else {
                                                mHeader.refresh();
                                            }
                                        }
                                    });
                                    if (CircleConstant.IS_FINISH_REFRESH) {
                                        break;
                                    }
                                    try {
                                        Thread.sleep(300);
                                    } catch (Exception e) {
                                        LogUtil.error(e + "");
                                    }
                                }
                            }
                        }, 1000);
                    }
                }
                return true;
            default:
                return true;
        }
    }

    public interface OnCircleRefreshListener {
        void completeRefresh();

        void refreshing();
    }


    public void finishRefresh() {
        float height = mChildView.getTranslationY();
        AnimatorValue backTopAni = new AnimatorValue();
        backTopAni.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                EventHandler eventHandler = new EventHandler(EventRunner.create());
                eventHandler.postTask(new Runnable() {
                    @Override
                    public void run() {
                        getContext().getUITaskDispatcher().asyncDispatch(new Runnable() {
                            @Override
                            public void run() {
                                if (mChildView != null) {
                                    mChildView.setTranslationY(height - (v * mPullHeight));
                                }
                                mHeader.getLayoutConfig().height = (int) (height - (v * mPullHeight));
                                if (v == 1) {
                                    if (mChildView != null) {
                                        mChildView.setTranslationY(0);
                                    }
                                    mHeader.getLayoutConfig().height = 0;
                                    mHeader.setVisibility(HIDE);
                                }
                            }
                        });
                    }
                }, 300);
                mHeader.invalidate();
            }
        });
        backTopAni.setDuration(500);
        backTopAni.start();
    }
}
